﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Framework.Comum.DAL;

namespace Framework.Comum.Tools
{
    public class Serializador
    {
        private List<object> Serializados = new List<object>();
        private int nivel = 0;

        public string JsonSerialize(object obj)
        {
            nivel++;

            var sb = new StringBuilder("{");
            //Following Types are used by Entity Framework. So no need to 
            //serialize those types.
            var ignoreEntityTypes = new List<Type> { typeof(System.Array), typeof(IRepositorio<>) };

            var t = (from s in ignoreEntityTypes select s.Name).ToList();

            var parentType = obj.GetType(); // I get type from given object 

            // use reflection to retrieve all properties of that type
            var ms = parentType.GetMembers().Where(v => v.MemberType
                == MemberTypes.Property && !t.Contains(v.GetType().Name)).ToList<MemberInfo>();

           
            const string doubleQuote = "\"";
            var counter = 0;
            var stringTypes = new List<String> { "String", "Guid", 
            "Boolean" };


            //    "EntityCollection`1", "EntityState", 
            //"EntityKey", "EntitySetName" };

            //Start iteration to navigate each property
            foreach (PropertyInfo p in ms)
            {
                //If property type is matched with ignoreTypes then
                //goto next loop
                if (ignoreEntityTypes.Contains(p.PropertyType))
                {
                    continue;
                }

                counter++;
                var propertyName = p.Name;
                var propertyType = p.PropertyType;
                var propertyValue = p.GetValue(obj, null);

                

                if (stringTypes.Contains(propertyType.Name))
                {
                    if (propertyValue == null)
                    {
                        sb.Append(doubleQuote + propertyName + doubleQuote +
                                  ":" + "null");
                    }

                    else
                    {
                        sb.Append(doubleQuote + propertyName + doubleQuote +
                            ":" + doubleQuote + propertyValue.ToString() + doubleQuote);
                    }
                }

                else if (propertyType != null && propertyType.IsPrimitive)
                {
                    sb.Append(doubleQuote + propertyName + doubleQuote
                        + ":" + propertyValue.ToString());
                }

                //Still I have doubt how Date Time will be handled.
                else if (propertyType.Name == "DateTime")
                {
                    var dt = (DateTime)propertyValue;
                    sb.Append(doubleQuote + propertyName
                        + doubleQuote + ":"
                        + "new Date(" + dt.Ticks.ToString() + ")");
                }
                else
                {
                    if (propertyValue != null)
                    {
                        sb.Append(doubleQuote + propertyType.Name + doubleQuote + ":");
                        //If property value is another entity, then
                        //call the method recursively.
                        sb.Append(JsonSerialize(propertyValue));
                    }
                    else
                    {
                        continue;
                    }
                }
                //If it is not the last property, then add comma
                if (counter < ms.Count)
                {
                    sb.Append(",");
                }
            }

            sb.Append("}");

            var result = sb.ToString().Replace(",}", "}");
            return result;
        }
    }
}